package com.rjkj.medicalwaste.repository

import android.util.Log
import androidx.lifecycle.LiveData
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.PagingSource
import com.rjkj.medicalwaste.bean.GarbageBean
import com.rjkj.medicalwaste.bean.GarbageStatus
import com.rjkj.medicalwaste.database.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.withContext

class GarbageRepository(val garbageDao: GarbageDao) {
    val TAG = "GarbageRepository"
    //检查箱子是否存在
    suspend fun findBoxByBoxCode(garbageBoxQRCode:String):List<BoxInfo>{
        return withContext(Dispatchers.IO){
            garbageDao.findBoxByBoxCode(garbageBoxQRCode)
        }
    }
    //获取所有未复核的医废袋
    fun getAllGarbageRequestUnReview(hospitalId: String, reviewStorageQRCode: String): Flow<PagingData<GarbageRequestUnReview>> {
        return Pager(config = PagingConfig(
                pageSize = 7,
                initialLoadSize = 7
        ), pagingSourceFactory = {
            garbageDao.getAllGarbageRequestUnReview(hospitalId, reviewStorageQRCode)
        }).flow
    }
    suspend fun getAllGarbageRequestUnReview2(hospitalId: String, reviewStorageQRCode: String): List<GarbageRequestUnReview> {
        return withContext(IO){
            garbageDao.getAllGarbageRequestUnReview2(hospitalId, reviewStorageQRCode)
        }
    }
    suspend fun findGarbageByCode2(code: String): GarbageBean? {
        return withContext(IO) {
            garbageDao.findGarbageByCode2(code)
        }
    }
    suspend fun findGarbageByBoxTime(code: String): List<GarbageBean> {
        return withContext(IO) {
            garbageDao.findGarbageByBoxTime(code)
        }
    }
    suspend fun findGarbageByBoxCode(code: String): List<GarbageBean> {
        return withContext(IO) {
            garbageDao.findGarbageByBoxCode(code)
        }
    }
    //复核医废袋更新数据
    suspend fun updateGarbageSetUnReview(garbageSetUnReview: GarbageSetUnReview): Int {
        return garbageDao.updateGarbageSetUnReview(garbageSetUnReview)
    }

    //装箱医废袋更新数据
    suspend fun updateGarbageSetBoxed(vararg garbageSetBoxed: GarbageSetBoxed): Int {
        return garbageDao.updateGarbageSetBoxed(*garbageSetBoxed)
    }

    //复核+装箱医废袋更新数据
    suspend fun updateGarbageSetReviewAndBoxed(garbageSetReviewAndBoxed: GarbageSetReviewAndBoxed): Int {
        return withContext(IO){
            garbageDao.updateGarbageSetReviewAndBoxed(garbageSetReviewAndBoxed)
        }
    }
    //复核+装箱医废袋更新数据
    suspend fun updateGarbageSetReviewAndBoxedList(list: List<GarbageSetReviewAndBoxed>){
        return withContext(IO){
            garbageDao.updateGarbageSetReviewAndBoxedList(list)
        }
    }
    //复核+装箱医废袋更新数据
    suspend fun updateGarbageSetReviewAndBoxedAddUserList(list: List<GarbageSetReviewAndBoxedAddUser>){
        return withContext(IO){
            garbageDao.updateGarbageSetReviewAndBoxedAddUserList(list)
        }
    }
    //医废袋入库更新数据
    suspend fun updateGarbageSetStorage2(garbageSetStorage: List<GarbageSetStorage>): Int {
        return withContext(IO){
            garbageDao.updateGarbageSetStorage2(garbageSetStorage)
        }
    }

    //box添加或删除要将所有的box内的医废信息更新
    suspend fun updateChangeGarbageFromBox(garbageBoxQRCode: String, garbageBoxWeight: String, garbageCNT: Int,garbageBoxTime:String) {
        return withContext(IO){
            garbageDao.updateChangeGarbageFromBox(garbageBoxQRCode, garbageBoxWeight, garbageCNT,garbageBoxTime)
        }
    }

    //医废袋入库更新数据
    suspend fun updateGarbageSetStorage(hospitalId: String, reviewStorageQRCode: String): Int {
        return garbageDao.updateGarbageSetStorage(hospitalId, reviewStorageQRCode)
    }

    //复核医废弹窗医废袋数据
    fun findGarbageReviewWeightDialogInfoByCode(code: String): LiveData<GarbageReviewWeightDialogInfo> {
        return garbageDao.findGarbageReviewWeightDialogInfoByCode(code)
    }
    suspend fun findGarbageReviewWeightDialogInfoByCode2(code: String): GarbageReviewWeightDialogInfo? {
        return withContext(IO){
            garbageDao.findGarbageReviewWeightDialogInfoByCode2(code)
        }
    }
    suspend fun getStateGarbage(hospitalId: String, state: String): List<GarbageBean> = withContext(Dispatchers.IO){
        garbageDao.getStateGarbage(hospitalId, state)
    }

    fun getStateGarbageBeanList(hospitalId: String, state: String): LiveData<List<GarbageBean>> = garbageDao.getStateGarbageToList(hospitalId, state)
    fun getStateGarbageByStoreCodeToList(hospitalId: String, state: String, reviewStorageQRCode: String): LiveData<List<GarbageBean>> = garbageDao.getStateGarbageByStoreCodeToList(hospitalId, state, reviewStorageQRCode)

    //箱列表临时箱表查询
    fun getTempBoxGarbageBeanList(hospitalId: String,storeRoomCode:String): LiveData<List<GarbageInTempBoxInfo>> {
        return garbageDao.getTempBoxGarbageBeanList(hospitalId,storeRoomCode)
    }

    //箱列表正常箱表查询
    fun getBoxGarbageBeanList(hospitalId: String,storeRoomCode:String): LiveData<List<GarbageInBoxInfo>> {
        return garbageDao.getBoxGarbageBeanList(hospitalId,storeRoomCode)
    }

    //箱列表正常箱表查询
    suspend fun getBoxGarbageBean(hospitalId: String, garbageBoxQRCode: String): List<GarbageInBoxInfo> {
        return withContext(IO){
            garbageDao.getBoxGarbageBean(hospitalId = hospitalId, garbageBoxQRCode = garbageBoxQRCode)
        }
    }

    fun getOpenBoxGarbagePagingSource(code: String): PagingSource<Int, GarbageBean> = garbageDao.getOpenBoxGarbage(code)


    //
//    fun getAllCollectGarbagePagingSource(hospitalId: String): PagingSource<Int, GarbageBean> = garbageDao.getAllCollectGarbage(hospitalId)
//
//
//    fun getStateGarbageBeanPagingSource(hospitalId: String, state: String): PagingSource<Int, GarbageBean> = garbageDao.getStateGarbageToPaging(hospitalId, state)
    suspend fun getMultiStateGarbageBeanList(hospitalId: String, roomId: String, states: Array<String>): List<GarbageBean> =
        withContext(Dispatchers.IO){garbageDao.getMultiStateGarbageToList2(hospitalId, roomId, states)}

    fun getMultiStateGarbageBeanList(hospitalId: String, states: Array<String>): LiveData<List<GarbageBean>> = garbageDao.getMultiStateGarbageToList(hospitalId, states)
    fun getMultiStateGarbageBeanPagingSource(hospitalId: String, states: Array<String>): PagingSource<Int, GarbageBean> = garbageDao.getMultiStateGarbageToPaging(hospitalId, states)

    suspend fun updateGarbageBeanState(list: List<GarbageRequestOutbound>) {
        return garbageDao.updateGarbageBeanState(list)
    }

    //    fun findGarbageByCode(code:String) :LiveData<GarbageBean>{
//        return garbageDao.findGarbageByCode(code)
//    }
    suspend fun findGarbageByCodeAndStatus(code: String, state: String = GarbageStatus.loading): GarbageDao.QueryGarbageRequestCodeAndState? {
        return garbageDao.findGarbageByCodeAndStatus(code, state)
    }

    //    suspend fun findGarbageByCode(code: String): GarbageDao.QueryGarbageRequestCodeAndState? {
//        return garbageDao.findGarbageByCodeAndStatus(code)
//    }
    suspend fun findGarbageByCodeAndStatusAndType(code: String, vararg state: String, type: String): GarbageDao.QueryGarbageRequestCodeAndState? {
        return garbageDao.findGarbageByCodeAndStatusAndType(garbageQRCode = code, *state, garbageType = type)
    }

    suspend fun updateGarbage(garbageBean: GarbageBean): Int {
        Log.e(TAG, "updateGarbage: ")
        return garbageDao.updateGarbageBean(garbageBean)
    }

    suspend fun updateOpenBoxAddGarbage(garbageRequestCodeAndState: GarbageRequestOpenBoxAddGarbage): Int {
        return garbageDao.updateOpenBoxAddGarbage(garbageRequestCodeAndState)
    }


    suspend fun updateGarbageBeanCodeList(list: List<GarbageRequestCodeAndState>): Int {
        Log.e(TAG, "updateGarbageBeanCode: ")
        return garbageDao.updateGarbageBeanCodeList(list)
    }

    suspend fun updateGarbageBeanCode(garbageRequestCodeAndState: GarbageRequestCodeAndState): Int {
        Log.e(TAG, "updateGarbageBeanCode: ")
        return garbageDao.updateGarbageBeanCode(garbageRequestCodeAndState)
    }

    suspend fun updateGarbageBeanTempCode(garbage: GarbageRequestTempCode): Int {
        Log.e(TAG, "updateGarbageBeanTempCode: ")
        return garbageDao.updateGarbageBeanTempCode(garbage)
    }

    suspend fun deleteGarbage(garbageBean: GarbageBean) {
        return garbageDao.deleteGarbage(garbageBean)
    }
    suspend fun deleteGarbage(codeList: List<String>) {
        withContext(IO){
            for (s in codeList) {
                garbageDao.deleteGarbageByCode(s)
            }
        }
    }
    suspend fun deleteAllGarbage() {
        withContext(IO){
            garbageDao.deleteAllGarbage()
        }
    }

    suspend fun insertGarbage(garbageBean: GarbageBean){
        withContext(IO){
            if(garbageDao.findGarbageByCode2(garbageBean.garbageQRCode)==null){
                garbageDao.insertGarbage(garbageBean)
            }
        }
    }

    suspend fun insertGarbageList(garbageBeanList: List<GarbageBean>) {
        withContext(IO){
            garbageDao.insertGarbageList(garbageBeanList)
        }
    }

    fun getOutboundGarbage(roomId: String, hospitalId: String): LiveData<List<GarbageBean>> {
        return garbageDao.findAllGarbageBoxedByRH(roomId, hospitalId)
    }

    suspend fun setOutboundGarbageStateToOutbound(list: List<GarbageSetOutbound>) {
        garbageDao.updateGarbageSetOutbound(list)
    }


    companion object {
        @Volatile
        private var instance: GarbageRepository? = null

        fun getInstance(garbageDao: GarbageDao): GarbageRepository =
                instance ?: synchronized(this) {
                    instance
                            ?: GarbageRepository(garbageDao).also {
                                instance = it
                            }
                }

    }
}